#include "common.h"
#include "cache.h"
#include "nemu.h"

uint32_t dram_read(hwaddr_t, size_t);
void dram_write(hwaddr_t, size_t, uint32_t);

/* Memory accessing interfaces */



uint32_t hwaddr_read(hwaddr_t addr, size_t len) {
	// Log("addr = %x, len = %zu,eip = %x", addr, len, cpu.eip);

	uint32_t tag = (addr >> 13) & 0x1ffff;

	if (tag == 0x3fff) {
		return dram_read(addr, len) & (~0u >> ((4 - len) << 3));
	}

	// 查找cache
	// int i;
	mem_cacheline cache_line;
	uint32_t data;
	if (cache_read(addr, &cache_line) ) {
		// cache 没有命中
		// 从内存读取64字节来填充cache，因为cache的行大小是64字节
        int i;
		for (i = 0; i < 64; i++) {
			cache_line.data[i] = dram_read((addr & 0xffffffc0) + i, 1);
		}
		// //查看读取的数据
		// for (i = 0; i < 64; i++) {
		// 	Log("cache_line.data[%d] = %x", i, cache_line.data[i]);
		// }
		// 将读取的数据写入cache
		cache_write(addr, &cache_line);
		
		// 从cache中读取数据
		cache_read(addr, &cache_line);

		// 从cacheline截取需要的数据
		memcpy(&data, cache_line.data + (addr & 0x3f), len);
		// 截取需要的数据
		data &= (~0u >> ((4 - len) << 3));

		// Log("data = %x", data);
		return data;
	}
	else {
		// cache 命中
		    // 从cacheline截取需要的数据
		memcpy(&data, cache_line.data + (addr & 0x3f), len);
		// 截取需要的数据
		data &= (~0u >> ((4 - len) << 3));
		// Log("data = %x", data);

		return data;
	}

	return dram_read(addr, len) & (~0u >> ((4 - len) << 3));
}



void hwaddr_write(hwaddr_t addr, size_t len, uint32_t data) {
	dram_write(addr, len, data);
}

uint32_t lnaddr_read(lnaddr_t addr, size_t len) {
	return hwaddr_read(addr, len);
}

void lnaddr_write(lnaddr_t addr, size_t len, uint32_t data) {
	hwaddr_write(addr, len, data);
}

uint32_t swaddr_read(swaddr_t addr, size_t len) {
#ifdef DEBUG
	assert(len == 1 || len == 2 || len == 4);
#endif
	return lnaddr_read(addr, len);
}

void swaddr_write(swaddr_t addr, size_t len, uint32_t data) {
#ifdef DEBUG
	assert(len == 1 || len == 2 || len == 4);
#endif
	lnaddr_write(addr, len, data);
}

